package org.belkodevelop.geocoding.adress.domen.type;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.belkodevelop.geocoding.adress.domen.CompositeAdress;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.Type;
import org.hibernate.usertype.CompositeUserType;

public class CompositeAdressType implements CompositeUserType {

    @Override
    public String[] getPropertyNames() {
        return new String[]{
            "room", 
            "floor", 
            "streetNumber", 
            "streetAddress", 
            "route", 
            "sublocality",
            "locality", 
            "administrativeAreaLevel3", 
            "administrativeAreaLevel2",
            "administrativeAreaLevel1", 
            "country" };
    }

    @Override
    public Type[] getPropertyTypes() {
        return new Type[] {
            Hibernate.STRING,
            Hibernate.SHORT,
            Hibernate.STRING,
            Hibernate.STRING,
            Hibernate.STRING,
            Hibernate.STRING,
            Hibernate.STRING,
            Hibernate.STRING,
            Hibernate.STRING,
            Hibernate.STRING,
            Hibernate.STRING
        };
    }

    @Override
    public Object getPropertyValue(Object object, int property) throws HibernateException {
        CompositeAdress compositeAdress = (CompositeAdress) object;
        switch (property) {
            case 0:
                return compositeAdress.getRoom();
            case 1:
                return compositeAdress.getFloor();
            case 2:
                return compositeAdress.getStreetNumber();
            case 3:
                return compositeAdress.getStreetAddress();
            case 4:
                return compositeAdress.getRoute();
            case 5:
                return compositeAdress.getSublocality();
            case 6:
                return compositeAdress.getLocality();
            case 7:
                return compositeAdress.getAdministrativeAreaLevel3();
            case 8:
                return compositeAdress.getAdministrativeAreaLevel2();
            case 9:
                return compositeAdress.getAdministrativeAreaLevel1();
            case 10:
                return compositeAdress.getCountry();
            default:
                throw new IllegalArgumentException("invalid property numer '" + property + "'");
        }
    }

    @Override
    public void setPropertyValue(Object component, int property, Object value) throws HibernateException {
        CompositeAdress compositeAdress = (CompositeAdress) component;
        switch (property) {
            case 0:
                compositeAdress.setRoom((String)value);
                break;
            case 1:
                compositeAdress.setFloor((Short)value);
                break;
            case 2:
                compositeAdress.setStreetNumber((String)value);
                break;
            case 3:
                compositeAdress.setStreetAddress((String)value);
                break;
            case 4:
                compositeAdress.setRoute((String)value);
                break;
            case 5:
                compositeAdress.setSublocality((String)value);
                break;
            case 6:
                compositeAdress.setLocality((String)value);
                break;
            case 7:
                compositeAdress.setAdministrativeAreaLevel3((String)value);
                break;
            case 8:
                compositeAdress.setAdministrativeAreaLevel2((String)value);
                break;
            case 9:
                compositeAdress.setAdministrativeAreaLevel1((String)value);
                break;
            case 10:
                compositeAdress.setCountry((String)value);
                break;
            default:
                throw new IllegalArgumentException("invalid property numer '" + property + "'");
        }
    }

    @Override
    public Class returnedClass() {
        return CompositeAdress.class;
    }

    @Override
    public boolean equals(Object object1, Object object2) throws HibernateException {
        if (object1 == null || object2 == null) {
            return false;
        }
        return object1.equals(object2);
    }

    @Override
    public int hashCode(Object object) throws HibernateException {
        if (object == null) {
            return 0;
        }
        return object.hashCode();
    }

    @Override
    public Object nullSafeGet(ResultSet rs, String[] strings, SessionImplementor si, Object o) throws HibernateException, SQLException {
        CompositeAdress compositeAdress = new CompositeAdress();
        compositeAdress.setRoom((String)Hibernate.STRING.nullSafeGet(rs, strings[0]));
        compositeAdress.setFloor((Short)Hibernate.SHORT.nullSafeGet(rs, strings[1]));
        compositeAdress.setStreetNumber((String)Hibernate.STRING.nullSafeGet(rs, strings[2]));
        compositeAdress.setStreetAddress((String)Hibernate.STRING.nullSafeGet(rs, strings[3]));
        compositeAdress.setRoute((String)Hibernate.STRING.nullSafeGet(rs, strings[4]));
        compositeAdress.setSublocality((String)Hibernate.STRING.nullSafeGet(rs, strings[5]));
        compositeAdress.setLocality((String)Hibernate.STRING.nullSafeGet(rs, strings[6]));
        compositeAdress.setAdministrativeAreaLevel3((String)Hibernate.STRING.nullSafeGet(rs, strings[7]));
        compositeAdress.setAdministrativeAreaLevel2((String)Hibernate.STRING.nullSafeGet(rs, strings[8]));
        compositeAdress.setAdministrativeAreaLevel1((String)Hibernate.STRING.nullSafeGet(rs, strings[9]));
        compositeAdress.setCountry((String)Hibernate.STRING.nullSafeGet(rs, strings[10]));
        return compositeAdress;
    }

    @Override
    public void nullSafeSet(PreparedStatement ps, Object value, int index, SessionImplementor si) throws HibernateException, SQLException {
        CompositeAdress compositeAdress = (CompositeAdress) value;
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getRoom(), index + 0);
        Hibernate.SHORT.nullSafeSet(ps, compositeAdress.getFloor(), index + 1);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getStreetNumber(), index + 2);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getStreetAddress(), index + 3);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getRoute(), index + 4);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getSublocality(), index + 5);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getLocality(), index + 6);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getAdministrativeAreaLevel3(), index + 7);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getAdministrativeAreaLevel2(), index + 8);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getAdministrativeAreaLevel1(), index + 9);
        Hibernate.STRING.nullSafeSet(ps, compositeAdress.getCountry(), index + 10);
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        if (value == null) { 
            return null;
        }
        CompositeAdress compositeAdress = (CompositeAdress)value;
        CompositeAdress newCompositeAdress = new CompositeAdress();
        newCompositeAdress.setRoom(compositeAdress.getRoom());
        newCompositeAdress.setFloor(compositeAdress.getFloor());
        newCompositeAdress.setStreetNumber(compositeAdress.getStreetNumber());
        newCompositeAdress.setStreetAddress(compositeAdress.getStreetAddress());
        newCompositeAdress.setRoute(compositeAdress.getRoute());
        newCompositeAdress.setSublocality(compositeAdress.getSublocality());
        newCompositeAdress.setLocality(compositeAdress.getLocality());
        newCompositeAdress.setAdministrativeAreaLevel3(compositeAdress.getAdministrativeAreaLevel3());
        newCompositeAdress.setAdministrativeAreaLevel2(compositeAdress.getAdministrativeAreaLevel2());
        newCompositeAdress.setAdministrativeAreaLevel1(compositeAdress.getAdministrativeAreaLevel1());
        newCompositeAdress.setCountry(compositeAdress.getCountry());
        return newCompositeAdress;
    }

    @Override
    public boolean isMutable() {
        return true;
    }

    @Override
    public Serializable disassemble(Object o, SessionImplementor si) throws HibernateException {
        return (Serializable)o;
    }

    @Override
    public Object assemble(Serializable srlzbl, SessionImplementor si, Object owner) throws HibernateException {
        return srlzbl;
    }

    @Override
    public Object replace(Object original, Object target, SessionImplementor si, Object owner) throws HibernateException {
        return deepCopy(original);
    }
    
}
